<template>
  <div class="scroll-box" ref="scrollBox" @scroll="handleScroll"
       :style="{ height: scrollHeight + 'px' }">

    <div class="virtual-list"
         :style="{ paddingTop: paddingTop + 'px', paddingBottom: paddingBottom + 'px' }">

      <div v-for="(item, index) in visibleItems" :key="index"
           :style="{ height: itemHeight + 'px' }">
        <van-loading color="#1989fa" v-if="loadingLock" />
        <slot name="item" :item="item" :index="index"></slot>
      </div>
    </div>

  </div>
</template>

<script setup>
import {ref, computed, onMounted, onUnmounted, watchEffect,nextTick} from 'vue'

const props = defineProps({
  listData: {type: Array, default: () => []},
  itemHeight: {type: Number, default: 50},
  scrollHeight: {type: Number, default: 300},
  loadMoreFunction: {type: Function, required: false},
  firstLoading: false,
})

console.log("内容:listData2",props.listData )
const visibleCount = computed(()=> Math.ceil(props.scrollHeight / props.itemHeight) + 1)
const start = ref(0)
const end = computed(() => Math.min(start.value + (2 * visibleCount.value - 1), renderData.value.length))
const paddingTop = computed(() => start.value * props.itemHeight)
const renderData = ref(props.listData ?  props.listData : [])
const paddingBottom = computed(() => (renderData.value.length - end.value) * props.itemHeight)
const visibleItems = computed(() => renderData.value.slice(start.value, end.value))
const scrollBox = ref(null);
let lastIndex = start.value;
const loadingLock = ref(false)

const handleScroll = rafThrottle(() => {
  onScrollToBottom();
  onScrolling();
  onScrollToTop();
});
const emit = defineEmits(['toTop'])

let loadFinish = false;
const scrollToIndex = (index) => {
  if (index < 0 || index >= renderData.value.length) {
    console.error("Index out of bounds");
    return;
  }
  // 计算滚动条位置
  const scrollTop = index * props.itemHeight;
  // 设置滚动条位置
  scrollBox.value.scrollTop = scrollTop;
}

const loadMore = (async () => {
  if (loadingLock.value) return;
  loadingLock.value = true;
  const moreData = await props.loadMoreFunction().catch(err => {
    console.error(err);
  })
  if (moreData && moreData.length !== 0) {
    // 历史有多少数据
    renderData.value = [...moreData, ...renderData.value];
    handleScroll();
    //加载完成后，需要修正距离
    if (moreData.length !== 0){
      scrollToIndex(moreData.length)
    }
  }
  if (!moreData || moreData.length === 0){
    if (!loadFinish){
      console.log("加载位置维持不变在顶部")
      scrollToIndex(0);
    }
    loadFinish = true;

  }
  loadingLock.value = false;
})
/**
 * 直接滚动到底部
 */
const scrollVirtualToBottom = () => {
  nextTick(() => {
    // 计算滚动条位置
    const scrollTop = renderData.value.length * props.itemHeight;
    // 在Vue更新DOM后执行滚动
    scrollBox.value.scrollTop = scrollTop;
  });
}

/**
 * 增量增加数据
 */
const addItem = (item)=>{
  renderData.value = [...renderData.value, item]
  onScrolling();
}


const onScrolling = () => {
  const scrollTop = scrollBox.value.scrollTop;
  // console.log("  scrollBox.value", scrollBox.value)
  // console.log("scrollTop", scrollTop)
  let thisStartIndex = Math.floor(scrollTop / props.itemHeight);
  const isSomeStart = thisStartIndex === lastIndex;
  if (isSomeStart) return;
  const isEndIndexOverListLen = thisStartIndex + 2 * visibleCount.value - 1 >= renderData.value.length;
  if (isEndIndexOverListLen) {
    thisStartIndex = renderData.value.length - (2 * visibleCount.value - 1);
  }
  lastIndex = thisStartIndex;
  start.value = thisStartIndex <= 0 ? 0 : thisStartIndex;
}

const onScrollToBottom = () => {
  const scrollTop = scrollBox.value.scrollTop;
  const clientHeight = scrollBox.value.clientHeight;
  const scrollHeight = scrollBox.value.scrollHeight;
  if (scrollTop + clientHeight >= scrollHeight) {
    // loadMore();
  }
}


watchEffect(() => {
  // renderData.value = [...props.listData]
  console.log("renderData.value ", [...props.listData] )
});
let onTop = false; // 定义一个状态标志
const onScrollToTop = () => {

  if(scrollBox.value.scrollTop === 0 && !onTop) {
    if (props.loadMoreFunction){
      console.log("到达顶部:onScrollToTop,加载loadmore")
      loadMore();
    }
    onTop = true; // 设置状态标记为 true
  } else if (scrollBox.value.scrollTop !== 0) {
    onTop = false; // 如果滚动条没有滚动到顶部，设置状态标记为 false
  }
}

function rafThrottle(fn) {
  let lock = false;
  return function (...args) {
    if (lock) return;
    lock = true;
    window.requestAnimationFrame(() => {
      fn.apply(args);
      lock = false;
    });
  };
}

defineExpose({
  scrollToIndex, scrollVirtualToBottom, addItem
})


onMounted(() => {
  scrollBox.value?.addEventListener('scroll', handleScroll);

});

onUnmounted(() => {
  scrollBox.value?.removeEventListener('scroll', handleScroll);
});

</script>

<style scoped>
.virtual-list {
  position: relative;
}

.scroll-box {
  overflow-y: auto;
}
</style>
